//
// Created by zcxsy on 2020/2/25.
//

#pragma warning(push, 0)
#include <glad/glad.h>
#include <error.h>
#include <stdio.h>
#pragma warning(pop)

static char buffer[4096];

static unsigned int compileShader(const char *code, int type) {
    unsigned int vertexShader;
    int success;
    vertexShader = glCreateShader(type);
    glShaderSource(vertexShader, 1, &code, NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 4096, NULL, buffer);
        errorAndExit(buffer);
    }
    return vertexShader;
}

static unsigned int linkShaderProgram(unsigned int vertexShader,
        unsigned int fragmentShader) {
    int success;
    unsigned int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) errorAndExit("Shader program link failed");
    return shaderProgram;
}

void shaderUse(unsigned int shaderProgram) {
    glUseProgram(shaderProgram);
}

unsigned int shaderInit(const char *vertexPath, const char *fragmentPath) {
    FILE *file;
    errno_t hasError;
    unsigned int vertexShader, fragmentShader, shaderProgram;
    size_t readSize;

    hasError = fopen_s(&file, vertexPath, "rb");
    if (hasError) errorAndExit("Error reading vertex shader file");
    readSize = fread(buffer, sizeof(char), 4096, file);
    buffer[readSize] = 0;
    if (ferror(file)) errorAndExit("Error reading vertex shader file");
    if (!feof(file)) errorAndExit("Vertex shader file too long");
    vertexShader = compileShader(buffer, GL_VERTEX_SHADER);

    hasError = fopen_s(&file, fragmentPath, "rb");
    if (hasError) errorAndExit("Error reading vertex shader file");
    readSize = fread(buffer, sizeof(char), 4096, file);
    buffer[readSize] = 0;
    if (ferror(file)) errorAndExit("Error reading vertex shader file");
    if (!feof(file)) errorAndExit("Vertex shader file too long");
    fragmentShader = compileShader(buffer, GL_FRAGMENT_SHADER);

    shaderProgram = linkShaderProgram(vertexShader, fragmentShader);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    return shaderProgram;
}